package com.oweight.sagacious.auth.client.jwt;

import com.oweight.sagacious.auth.client.config.ServiceAuthConfig;
import com.oweight.sagacious.auth.client.feign.ServiceAuthFeign;
import com.oweight.sagacious.auth.common.util.jwt.IJWTInfo;
import com.oweight.sagacious.auth.common.util.jwt.JWTHelper;
import com.oweight.sagacious.common.constant.CommonConstants;
import com.oweight.sagacious.common.exception.auth.ClientTokenException;
import com.oweight.sagacious.api.model.msg.Message;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.List;

/**
 * JWT申请服
 * <p>
 * 其中ServiceAuthUtil 会读取配置中的关于服务鉴权的基础配置
 * auth:
 * serviceId: sage-auth-service
 * user:
 * token-header: Authorization
 * # 此处就是我们的鉴权服务的配置
 * client:
 * token-header: x-client-token
 * id:  #不不填则默认读取spring.application.name
 * secret: 123456
 * <p>
 *
 * @author ace
 * @date 2017/9/15
 */
@Configuration
@Slf4j
@EnableScheduling
public class ServiceAuthUtil {

    @Autowired
    private ServiceAuthConfig serviceAuthConfig;

    @Autowired
    private ServiceAuthFeign serviceAuthFeign;

    private List allowedClient;

    private String clientToken;

    /**
     * 解析Token信息
     *
     * @param token token
     * @return com.oweight.sagacious.auth.common.util.jwt.IJWTInfo
     * @author zhougm
     * @version 2019/10/19 14:54
     */
    public IJWTInfo getInfoFromToken(String token) throws Exception {
        try {
            return JWTHelper.getInfoFromToken(token, serviceAuthConfig.getPubKeyByte());
        } catch (ExpiredJwtException ex) {
            throw new ClientTokenException("客户端Token失效！");
        } catch (SignatureException ex) {
            throw new ClientTokenException("客户端Token签名错误！");
        } catch (IllegalArgumentException ex) {
            throw new ClientTokenException("客户端Token为空！");
        }
    }

    /**
     * 定时刷新可以访问的服务列列表
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void refreshAllowedClient() {
        log.debug("refresh allowedClient.....");
        Message resp = serviceAuthFeign.getAllowedClient(serviceAuthConfig.getClientId(), serviceAuthConfig.getClientSecret());
        if (resp.status() == CommonConstants.SU_DEFAULT_OK_CODE) {
            this.allowedClient = resp.getData(List.class);
        }
    }

    /**
     * 定时刷新可访问的服务JWT
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void refreshClientToken() {
        log.debug("refresh client token.....");
        Message resp = serviceAuthFeign.getAccessToken(serviceAuthConfig.getClientId(), serviceAuthConfig.getClientSecret());
        if (resp.status() == CommonConstants.SU_DEFAULT_OK_CODE) {
            this.clientToken = resp.getData(String.class);
        }
    }


    public String getClientToken() {
        if (this.clientToken == null) {
            this.refreshClientToken();
        }
        return clientToken;
    }

    public List<String> getAllowedClient() {
        if (this.allowedClient == null) {
            this.refreshAllowedClient();
        }
        return allowedClient;
    }
}
